Skip to main content

路由中间件之 AddQueuedCookiesToResponse

简介

[
'App\Http\Middleware\EncryptCookies',
'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
'Illuminate\Session\Middleware\StartSession',
'Illuminate\View\Middleware\ShareErrorsFromSession',
'App\Http\Middleware\VerifyCsrfToken',
'Illuminate\Routing\Middleware\SubstituteBindings',
'App\Http\Middleware\RedirectIfAuthenticated',
]

如上,前面一章我们讲解了 EncryptCookies 路由中间件的作用。

这一章我们来看一下 AddQueuedCookiesToResponse 路由中间件的作用。

从字面上来看,不难看出,大概指从某个专门管理 Cookie 的队列服务中,取出 Cookie 加入到响应中。

所谓 Cookie 容器服务指提供 Cookie 管理功能的类。即:Illuminate\Cookie\CookieJar

此服务,主要有:

  • 获取 Symfony\Component\HttpFoundation\Cookie 真实 Cookie 对象实例的方法
  • 利用如下数组,实现 Cookie 列表数据的管理

Illuminate\Cookie\CookieJar

protected $queued = [];

AddQueuedCookiesToResponse 中间件

中间件核心方法 handle 方法如下所示:

public function handle($request, Closure $next)
{
// 从 Laravel 内层获取响应
$response = $next($request);

// 直接获取 queued 数组,循环将 Cookie 取出并附加到响应头中
foreach ($this->cookies->getQueuedCookies() as $cookie) {
$response->headers->setCookie($cookie);
}

// 将响应抛给外层
return $response;
}

问题一:$this->cookies 从哪里来的

<?php

namespace Illuminate\Cookie\Middleware;

use Closure;
// 重点在这,利用 特别篇5 的讲解方式,我们知道 CookieJar 实际指向的是 Illuminate\Cookie\CookieJar
use Illuminate\Contracts\Cookie\QueueingFactory as CookieJar;

class AddQueuedCookiesToResponse
{
// 声明存储 Cookie 容器服务的属性
protected $cookies;

// 标准 IoC/DI 操作
public function __construct(CookieJar $cookies)
{
$this->cookies = $cookies;
}

// ... 省略若干代码
}

由此得知,$this->cookiesIlluminate\Cookie\CookieJar 的实例。

问题二: getQueuedCookies 方法在哪?

接续问题一,我们很容易就知道 getQueuedCookies 方法在 Illuminate\Cookie\CookieJar

public function getQueuedCookies()
{
return $this->queued;
}

直接返回了 $this->queued 数组

问题三:$this->queued 如何被赋值的?

讲这个问题之前,我们先看一下官方文档的一段内容

file

此段内容的位置 ---> 传送门

我们来看最下面这两段代码

Cookie::queue(Cookie::make('name', 'value', $minutes));

Cookie::queue('name', 'value', $minutes);

其中 Cookie 是 'cookie' 单词标识的门面,最终指向的对象恰恰就是 Illuminate\Cookie\CookieJar

我们看一下它的 queue 方法

public function queue(...$parameters)
{
// 验证第一个参数是否属于 Symfony\Component\HttpFoundation\Cookie 的实例
if (head($parameters) instanceof Cookie) {
// 如果第一个参数是 Symfony\Component\HttpFoundation\Cookie 的实例,则取出赋值个 $cookie
$cookie = head($parameters);
} else {
// 如果第一个参数不是属于 Symfony\Component\HttpFoundation\Cookie 的实例,那么则根据这些参数调用 make 方法,获取 Symfony\Component\HttpFoundation\Cookie 的实例。
$cookie = call_user_func_array([$this, 'make'], $parameters);
}

// 核心!!!,以关联数组的形式存储 Cookie
$this->queued[$cookie->getName()] = $cookie;
}

看到了没,if 语句判断的两种情况正好是官方文档所示的两种操作。